package com.example.demo.service.impl

import com.example.demo.dao.TBoardMessageDao
import com.example.demo.dao.TDeviceDao
import com.example.demo.dao.TPressureDao
import com.example.demo.dao.TTemperatureDao
import com.example.demo.dao.Tables.tDevices
import com.example.demo.dao.Tables.tJzrDepts
import com.example.demo.dao.Tables.tJzrInfo
import com.example.demo.dao.Tables.tJzrOrders
import com.example.demo.dao.Tables.tPressures
import com.example.demo.dao.Tables.tTemperatures
import com.example.demo.dao.Tables.vJzrInpatientFeeRecords
import com.example.demo.service.BedService
import com.example.demo.utils.GmrDatabase
import com.example.demo.utils.WebDatabase
import com.example.demo.vo.*
import me.liuwj.ktorm.dsl.*
import me.liuwj.ktorm.entity.filter
import me.liuwj.ktorm.entity.find
import me.liuwj.ktorm.entity.firstOrNull
import me.liuwj.ktorm.entity.toList
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.time.LocalDateTime

@Service
class BedServiceImpl(
    @Autowired
    private val webDatabase: WebDatabase,
    @Autowired
    private val gmrDatabase: GmrDatabase
) : BedService {

    override fun getBedCardInfo(deptCode: String, bedCode: String): BedInfoVo? {
//        gmrDatabase.getDataBase()
//            .from(TJzrInfoDao)
//            .select()
//            .whereWithConditions {
//                deptCode.let { deptid ->
//                    it += TJzrInfoDao.DEPT_CODE eq deptid.toInt()
//                }
//                bedCode.let { bedCode ->
//                    it += TJzrInfoDao.BED_NO eq bedCode
//                }
//            }.let { query ->
//                query.forEach {
//                    val bedInfoVo = BedInfoVo()
//                    bedInfoVo.infoVo = InfoVo().getVo(it)
//                    gmrDatabase.getDataBase()
//                        .from(TJzrOrderDao)
//                        .select()
//                        .whereWithConditions {
//                            bedInfoVo.infoVo?.id?.let { id ->
//                                it += TJzrOrderDao.PATIENT_ID eq id.toInt()
//                            }
//                            it += TJzrOrderDao.ORDER_CODE eq "1"
//                        }.let { query ->
//                            val orderVoList = mutableListOf<OrderVo>()
//                            query.forEach {
//                                orderVoList.add(OrderVo().getVo(it))
//                            }
//                            orderVoList.groupBy {
//                                it.START_TIME
//                            }.let { map ->
//                                var key: LocalDateTime? = null
//                                map.keys.lastOrNull()?.let {
//                                    key = it
//                                }
//                                key?.let {
//                                    bedInfoVo.bedSideCareLabelVo = map[it]
//                                }
//                            }
//                        }
//                    return bedInfoVo
//                }
//            }


        gmrDatabase.getDataBase().tJzrInfo.find {
            it.BED_NO eq bedCode
            it.DEPT_CODE eq deptCode.toInt()
        }?.let {
            val bedInfoVo = BedInfoVo()
            val info = InfoVo().getVo(it)
            bedInfoVo.infoVo = info
            val careLabelVo = mutableListOf<OrderVo>()
            gmrDatabase.getDataBase().tJzrOrders.filter {
                it.PATIENT_ID eq info.id.toInt()
                it.ORDER_CODE eq "1"
            }.toList()
                .toList().let {
                    val list = OrderVo().getListVo(it)
                    list.groupBy {
                        it.START_TIME
                    }.let { map ->
                        var key: LocalDateTime? = null
                        map.keys.lastOrNull()?.let {
                            key = it
                        }
                        key?.let {
                            bedInfoVo.bedSideCareLabelVo = map[it]
                        }
                    }
                }
//                .forEach {
//                    val bedsideCareLabelVo = OrderVo()
//                    val orderVo = OrderVo().getVo(it)
////                bedsideCareLabelVo.labelName = orderVo.ORDER_NAME
//                    careLabelVo.add(orderVo)
//                }
//            bedInfoVo.bedSideCareLabelVo = careLabelVo
            return bedInfoVo
        }
        return null
    }

    override fun getDeptList(): List<DeptVo>? {
        gmrDatabase.getDataBase().tJzrDepts.toList().let { list ->
            DeptVo().getListVo(list).let {
                return it
            }
        }
    }

    override fun getBedList(deptCode: String): BedInfoVoList? {
//        gmrDatabase.getDataBase().tJzrBeds.filter {
//            it.DEPT_CODE eq deptCode
//        }.toList().let {
//            return BedVo().getListVo(it)
//        }

        val infoVoList = BedInfoVoList()
        val infoVo = mutableListOf<InfoVo>()
        gmrDatabase.getDataBase().tJzrInfo.filter {
            it.DEPT_CODE eq deptCode.toInt()
        }.toList().forEach {
            infoVo.add(InfoVo().getVo(it))
        }
        infoVoList.infoVo = infoVo
        return infoVoList
    }

    override fun getBindToBed(
        deptCode: String,
        deptName: String,
        bedCode: String,
        bedName: String,
        deviceNo: String,
        deviceMac: String,
        deviceIp: String,
        appVersion: String,
        deviceType: String
    ): Int? {
        webDatabase.getDataBase().tDevices.filter {
            it.device_no eq deviceNo
        }.firstOrNull()?.let {
            webDatabase.getDataBase().update(TDeviceDao) {
                set(it.dept_code, deptCode)
                set(it.dept_name, deptName)
                set(it.app_version, appVersion)
                set(it.bed_code, bedCode)
                set(it.bed_name, bedName)
                set(it.device_ip, deviceIp)
                set(it.device_mac, deviceMac)
                set(it.device_type, deviceType.toInt())
                set(it.device_no, deviceNo)
                where {
                    it.device_no eq deviceNo
                }
            }.let {
                return it
            }
        } ?: let {
            webDatabase.getDataBase().insertAndGenerateKey(TDeviceDao) {
                set(it.dept_code, deptCode)
                set(it.dept_name, deptName)
                set(it.app_version, appVersion)
                set(it.bed_code, bedCode)
                set(it.bed_name, bedName)
                set(it.device_ip, deviceIp)
                set(it.device_mac, deviceMac)
                set(it.device_type, deviceType.toInt())
                set(it.device_no, deviceNo)
            }.let {
                return it.toString().toInt()
            }
        }
    }

    override fun getDeptDiviceNo(deptCode: String): DeptDeviceNoVO? {
//        webDatabase.getDataBase().tDevices.find {
//            it.dept_code eq deptCode
//            it.device_type eq 2getBedCardInfo
//        }?.let {
//            val deptDeviceNoVO = DeptDeviceNoVO()
//            deptDeviceNoVO.deviceNo = DeviceVo().getVo(it).device_no
//            return deptDeviceNoVO
//        } ?: return null
        webDatabase.getDataBase().tDevices.filter {
            it.device_type eq 2
        }.filter {
            it.dept_code eq deptCode
        }.firstOrNull()?.let {
            val deptDeviceNoVO = DeptDeviceNoVO()
            deptDeviceNoVO.deviceNo = DeviceVo().getVo(it).device_no
            return deptDeviceNoVO
        } ?: return null
    }


    override fun addTermometerValue(
        patientId: Int?,
        patientName: String?,
        deptId: Int?,
        deptName: String?,
        bedId: Int?,
        bedName: String?,
        date: String?,
        temperature: String?
    ): Int? {
        webDatabase.getDataBase().insertAndGenerateKey(TTemperatureDao) {
            set(it.patientId, patientId)
            set(it.patientName, patientName)
            set(it.deptId, deptId)
            set(it.deptName, deptName)
            set(it.bedId, bedId)
            set(it.bedName, bedName)
            set(it.date, date)
            set(it.temperature, temperature)
        }.let {
            return it.toString().toInt()
        }
    }

    override fun getTermometerValue(id: Int): TemperatureVo? {
        webDatabase.getDataBase().tTemperatures.find {
            it.id eq id
        }?.let {
            return TemperatureVo().getVo(it)
        }
        return null
    }

    override fun getTermometerValueList(deptId: Int?, patientId: Int?, patientName: String?): List<TemperatureVo>? {
        webDatabase.getDataBase()
            .from(TTemperatureDao)
            .select()
            .whereWithConditions {
                deptId?.let { deptId ->
                    it += TTemperatureDao.deptId eq deptId
                }
                patientId?.let { patientId ->
                    it += TTemperatureDao.patientId eq patientId
                }
                patientName?.let { patientName ->
                    it += TTemperatureDao.patientName eq patientName
                }
            }.let { query ->
                val temperatureVoList = mutableListOf<TemperatureVo>()
                query.forEach {
                    temperatureVoList.add(TemperatureVo().getVo(it))
                }
                return temperatureVoList
            }
    }

    override fun addPressureValue(
        patientId: Int?,
        patientName: String?,
        deptId: Int?,
        deptName: String?,
        bedId: Int?,
        bedName: String?,
        date: String?,
        highPress: String?,
        lowPress: String?,
        heartRate: String?
    ): Int? {
        webDatabase.getDataBase().insertAndGenerateKey(TPressureDao) {
            set(it.patientId, patientId)
            set(it.patientName, patientName)
            set(it.deptId, deptId)
            set(it.deptName, deptName)
            set(it.bedId, bedId)
            set(it.bedName, bedName)
            set(it.date, date)
            set(it.highPress, highPress)
            set(it.lowPress, lowPress)
            set(it.heartRate, heartRate)
        }.let {
            return it.toString().toInt()
        }
    }

    override fun getPressureValue(id: Int): PressureVo? {
        webDatabase.getDataBase().tPressures.find {
            it.id eq id
        }?.let {
            return PressureVo().getVo(it)
        }
        return null
    }

    override fun getPressureValueList(deptId: Int?, patientId: Int?, patientName: String?): List<PressureVo>? {
        webDatabase.getDataBase()
            .from(TPressureDao)
            .select()
            .whereWithConditions {
                deptId?.let { deptId ->
                    it += TPressureDao.deptId eq deptId
                }
                patientId?.let { patientId ->
                    it += TPressureDao.patientId eq patientId
                }
                patientName?.let { patientName ->
                    it += TPressureDao.patientName eq patientName
                }
            }.let { query ->
                val pressureVoList = mutableListOf<PressureVo>()
                query.forEach {
                    pressureVoList.add(PressureVo().getVo(it))
                }
                return pressureVoList
            }
    }

    override fun getBoardMessage(deptId: Int?, messageType: String?, start: Int, end: Int): List<BoardMessageVo>? {
        webDatabase.getDataBase()
            .from(TBoardMessageDao)
            .select()
            .whereWithConditions {
                deptId?.let { deptId ->
                    it += TBoardMessageDao.deptId eq deptId
                }
                messageType?.let { messageType ->
                    it += TBoardMessageDao.messageType eq messageType
                }
            }
            .limit(start, end)
            .orderBy(TBoardMessageDao.id.desc())
            .let {
                val boardMessageVoList = mutableListOf<BoardMessageVo>()
                it.forEach {
                    boardMessageVoList.add(BoardMessageVo().getVo(it))
                }
                return boardMessageVoList
            }
    }

    override fun getFeeList(patientId: String): List<FeeVo> {
        gmrDatabase.getDataBase().vJzrInpatientFeeRecords.filter {
            it.PATIENT_ID eq patientId
        }.toList().let {
            return FeeVo().getListVo(it)
        }
    }

}

